package com.creator.paas.service;

import net.sourceforge.tess4j.ITesseract;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Size;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.bytedeco.opencv.global.opencv_imgcodecs.imread;
import static org.bytedeco.opencv.global.opencv_imgcodecs.imwrite;
import static org.bytedeco.opencv.global.opencv_imgproc.*;

public class InvoiceParser {
    private final ITesseract tesseract;
    
    public InvoiceParser(String tessDataPath) {
        tesseract = new Tesseract();
        tesseract.setDatapath(tessDataPath);
        tesseract.setLanguage("chi_sim+eng");
    }
    
    // 保持原有的preprocessImage方法不变...
    public void preprocessImage(String inputImagePath, String outputImagePath) {
        Mat src = imread(inputImagePath);
        if (src.empty()) {
            throw new RuntimeException("无法读取图像: " + inputImagePath);
        }
        
        Mat gray = new Mat();
        cvtColor(src, gray, opencv_imgproc.COLOR_BGR2GRAY);
        
        Mat blurred = new Mat();
        GaussianBlur(gray, blurred, new Size(3, 3), 0);
        
        Mat binary = new Mat();
        threshold(blurred, binary, 0, 255, THRESH_BINARY_INV + THRESH_OTSU);
        
        imwrite(outputImagePath, binary);
        
        src.release();
        gray.release();
        blurred.release();
        binary.release();
    }
    
    /**
     * 修改OCR识别方法，使用BufferedImage避免输入流问题
     */
    public Map<String, String> extractInvoiceInfo(String imagePath) throws TesseractException, IOException {
        // 先验证文件是否存在且可读取
        File imageFile = new File(imagePath);
        if (!imageFile.exists() || !imageFile.canRead()) {
            throw new IOException("无法读取图像文件: " + imagePath);
        }
        
        // 尝试多种方式读取图像
        BufferedImage image = null;
        try {
            // 方式1: 使用ImageIO直接读取
            image = ImageIO.read(imageFile);
        } catch (Exception e) {
            System.err.println("ImageIO读取失败，尝试备用方式: " + e.getMessage());
            // 方式2: 先保存为PNG格式再读取（解决JPEG格式问题）
            String tempPngPath = imagePath.replace(".jpg", ".png").replace(".jpeg", ".png");
            Mat mat = imread(imagePath);
            imwrite(tempPngPath, mat);
            mat.release();
            image = ImageIO.read(new File(tempPngPath));
        }
        
        if (image == null) {
            throw new IOException("无法解析图像文件: " + imagePath);
        }
        
        // 使用BufferedImage进行OCR识别，避免输入流问题
        String text = tesseract.doOCR(image);
        System.out.println("识别到的文本:\n" + text);
        
        // 提取发票信息（保持不变）
        Map<String, String> invoiceInfo = new HashMap<>();
        invoiceInfo.put("invoiceNumber", extractPattern(text, "发票号码[:：]?\\s*([0-9]{8,12})"));
        invoiceInfo.put("invoiceCode", extractPattern(text, "发票代码[:：]?\\s*([0-9]{10,12})"));
        invoiceInfo.put("issueDate", extractPattern(text, "开票日期[:：]?\\s*([0-9]{4}年[0-9]{1,2}月[0-9]{1,2}日)"));
        invoiceInfo.put("purchaser", extractPattern(text, "购买方[:：]?\\s*([^\n]+)"));
        invoiceInfo.put("seller", extractPattern(text, "销售方[:：]?\\s*([^\n]+)"));
        invoiceInfo.put("amount", extractPattern(text, "价税合计[:：]?\\s*([\\d,.]+)"));
        
        return invoiceInfo;
    }
    
    // 保持原有的extractPattern方法不变...
    private String extractPattern(String text, String pattern) {
        Matcher matcher = Pattern.compile(pattern).matcher(text);
        if (matcher.find()) {
            return matcher.group(1).trim();
        }
        return "";
    }
    
    public static void main(String[] args) {
        try {
            // 设置正确的路径
//            String tessDataPath = "/usr/local/share/tessdata";  // Linux/macOS
             String tessDataPath = "C:\\Program Files\\Tesseract-OCR\\tessdata";  // Windows
            
            String inputImage = "C:\\Users\\T460s\\Desktop\\2.png"; // 替换为你的图片路径
            String processedImage = "C:\\Users\\T460s\\Desktop\\processed_invoice.jpg";
            
            // 验证路径
            validatePath(tessDataPath, true);
            validatePath(inputImage, false);
            
            // Windows系统特殊设置
            if (System.getProperty("os.name").toLowerCase().contains("win")) {
                System.setProperty("jna.library.path", "C:\\Program Files\\Tesseract-OCR\\lib");
            }
            
            InvoiceParser parser = new InvoiceParser(tessDataPath);
            parser.preprocessImage(inputImage, processedImage);
            validatePath(processedImage, false);  // 验证处理后的图像是否生成
            
            Map<String, String> invoiceInfo = parser.extractInvoiceInfo(processedImage);
            
            System.out.println("\n提取的发票信息:");
            invoiceInfo.forEach((key, value) -> System.out.println(key + ": " + value));
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private static void validatePath(String path, boolean isDirectory) {
        File file = new File(path);
        if (!file.exists()) {
            throw new RuntimeException("路径不存在: " + path);
        }
        if (isDirectory && !file.isDirectory()) {
            throw new RuntimeException("不是目录: " + path);
        }
        if (!isDirectory && !file.isFile()) {
            throw new RuntimeException("不是文件: " + path);
        }
        if (!file.canRead()) {
            throw new RuntimeException("没有读取权限: " + path);
        }
    }
}
